from zflow import *

class OnehotSel(ZGraph):
    '''OnehotSel: this is a graph that selects one datum out of severals
       Parameters:
           cnt: the number of input to be selected
            type_width_example(int,ZBundle): can be a int or a example or a class inherites ZBundle
       ipads:
           sel: the onehot datum used to select input
        ins[?]: the ?th input datum, the number of ins is controled by the cnt parameter
       opads:
           out: the selected output
    '''
    def __init__(self,name,cnt,type_width_example):
        super().__init__(name)
        # the onehot selection datum
        self.add_ipad(ZDatum('sel',cnt))
        self.creator = ZCreator(type_width_example)

        # the final output datum
        self.add_opad(self.creator('out'))
        width = self.out.width
        self.width = width
        
        self.ins = []
        # the input datums
        in_datums = dict()
        in_datums[0] = self.add_ipad(self.creator('in_0'))
        self.ins.append(in_datums[0])
        if self.sel.width == 1:
            self.out.val = self.ins[0]
        else:
            tmps = '{width{sel[0]}} & in_datums[0]\n'
            it = self.add(ZProperty('onehot_sel_cov_0',cov,"onehot signal %s's bit %d should have been high"%(self.sel.get_path(),0)))
            it.val = 'sel[0]'
            for i in range(1,cnt):
                in_datums[i] = self.add_ipad(self.creator(v('in_i')))
                self.ins.append(in_datums[i])
                tmps += '    | {width{sel[%d]}} & in_datums[%d] \n' %(i,i)
                it = self.add(ZProperty('onehot_sel_cov_%d'%i,cov,"onehot signal %s's bit %d should have been high"%(self.sel.get_path(),i)))
                it.val = 'sel[i]'
            self.out.val = tmps
        it = self.add(ZProperty('onehot_sel_assert',ast,'only one bit of the sel should be 1'))
        it.val = '$onehot0(sel)'